﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
using System.IO;
using System.Security.Cryptography;


namespace Kit
{
    public enum HashType { MD5, SHA1, SHA256, SHA512 };


    class ChrisKit
    {
        private const string kAppDataDir = "CCPSIP_MsgPush";


        /// <summary>
        /// 把訊息寫入到每天的Log檔案
        /// </summary>
        /// <param name="logMsg">要log的訊息</param>
        public static void AppendToDayLog(string logMsg)
        {
            string appDataRoot = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData);
            string logDir = string.Format(@"{0}\{1}\logs", appDataRoot, kAppDataDir);
            if (!Directory.Exists(logDir))
            {
                Directory.CreateDirectory(logDir);
            }

            string filePath = string.Format(@"{0}\{1:yyyy-MM-dd}.log", logDir, DateTime.Now);
            StreamWriter logWriter = File.AppendText(filePath);
            logWriter.Write("[{0:HH:mm:ss}] {1}", DateTime.Now, logMsg);
            logWriter.Write(Environment.NewLine);
            logWriter.Flush();
            logWriter.Close();
        }


        /// <summary>
        /// Get Hash String
        /// </summary>
        /// <param name="str">Input string</param>
        /// <param name="hashType">Hash function type</param>
        /// <returns></returns>
        public static string getHashStr(string str, HashType hashType)
        {
            HashAlgorithm hashObj;

            if (hashType == HashType.MD5)
                hashObj = new MD5CryptoServiceProvider();
            else if (hashType == HashType.SHA1)
                hashObj = new SHA1Managed();
            else if (hashType == HashType.SHA256)
                hashObj = new SHA256Managed();
            else if (hashType == HashType.SHA512)
                hashObj = new SHA512Managed();
            else
                return null;

            byte[] hashBytes = hashObj.ComputeHash(System.Text.Encoding.UTF8.GetBytes(str));
            hashObj.Clear();

            string hashStr = "";
            for (int i = 0; i < hashBytes.Length; i++)
            {
                hashStr += hashBytes[i].ToString("x2");
            }
            return hashStr;
        }


        /// <summary>
        /// 將Exception轉成XML格式的字串
        /// </summary>
        /// <param name="ex">要轉換的Exception物件</param>
        /// <param name="includeStackTrace">要不要包含StackTrace</param>
        /// <returns>Exception詳細資訊(XML格式字串)</returns>
        public static string Ex2Xml(Exception ex, bool includeStackTrace)
        {
            string result = "<Exception>"
              + Environment.NewLine + "<Type>" + ex.GetType().Name + "</Type>"
              + Environment.NewLine + "<Message>" + ex.Message + "</Message>";

            if (includeStackTrace)
            {
                result += Environment.NewLine + "<StackTrace>";
                result += System.Web.HttpUtility.HtmlEncode(ex.StackTrace) + "</StackTrace>";
            }
            result += Environment.NewLine + "</Exception>";
            return result;
        }


        public static string Ex2Xml(System.Net.Sockets.SocketException sEx)
        {
            string result = "<Exception>"
              + Environment.NewLine + "<Type>" + sEx.GetType().Name + "</Type>"
              + Environment.NewLine + "<ErrorCode>" + sEx.ErrorCode + "</ErrorCode>"
              + Environment.NewLine + "<SocketError>" + sEx.SocketErrorCode + "</SocketError>"
              + Environment.NewLine + "<Message>" + sEx.Message + "</Message>"
              + Environment.NewLine + "<StackTrace>"
              + System.Web.HttpUtility.HtmlEncode(sEx.StackTrace) + "</StackTrace>"
              + Environment.NewLine + "</Exception>";
            return result;
        }


        #region Query String Functions


        public static string DictToQueryStr(Dictionary<string, string> paramDict, Encoding enc)
        {
            string resultStr = "";
            foreach (KeyValuePair<string, string> param in paramDict)
            {
                string encValue = System.Web.HttpUtility.UrlEncode(param.Value, enc);
                resultStr += string.Format("&{0}={1}", param.Key, encValue);
            }
            return resultStr.Substring(1);
        }


        public static string UrlEncodeUpper(string urlStr, Encoding enc)
        {
            string encUrl = System.Web.HttpUtility.UrlEncode(urlStr, enc);
            const string pattern = "%([0-9][a-f]|[a-f][0-9]|[a-f]{2})";
            return Regex.Replace(encUrl, pattern, m => m.Value.ToUpper());
        }


        #endregion



        public static UInt64 ToUnixTime(DateTime time)
        {
            TimeSpan unixTimeTS = time.ToUniversalTime() - new DateTime(1970, 1, 1);
            return Convert.ToUInt64(unixTimeTS.TotalSeconds);
        }


        /// <summary>
        /// Use this function to skip the CS0168 warning.
        /// For example:
        /// "The variable 'ex' is declared but never used"
        /// </summary>
        /// <param name="obj"></param>
        public static void SkipVar(object obj)
        {
            // Use this function to skip unused variable
        }

    }
}
